package rs.udd.service.document.searcher.analyzed;

import java.io.File;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.Version;

import rs.udd.model.Agent;
import rs.udd.service.document.searcher.ResultRetriever;
import rs.udd.service.util.FileUtil;
import rs.udd.service.util.SecurityUtil;

public class AnalyzedSearcher{
	protected static final Version v = Version.LUCENE_4_9;
	protected File indexDirPath;
	protected Analyzer analyzer;
	
	public AnalyzedSearcher(Analyzer analyzer){
		this(FileUtil.getIndicesPath(), analyzer);
	}
	
	public AnalyzedSearcher(String path, Analyzer analyzer){
		this(new File(path), analyzer);
	}
	
	public AnalyzedSearcher(File indexDirPath, Analyzer analyzer){
		this.indexDirPath = indexDirPath;
		if(analyzer == null){
			throw new NullPointerException("Morate zadati analyzer");
		}
		this.analyzer = analyzer;
	}
	
	public List<Document> search(Term term) {
		try {
			Query query = createQuery(term);
			return ResultRetriever.getResults(query, this.indexDirPath);
		} catch (ParseException e) {
			throw new IllegalArgumentException("Prosledjeni term nije u redu");
		}
	}
	
	public List<Document> search(Query query) {
		return ResultRetriever.getResults(query, this.indexDirPath);
	}
	
	public List<Document> search(Term... terms) {
		BooleanQuery bQuery = new BooleanQuery();
		
		try {
			for (Term term : terms) {
				Query query = createQuery(term);
				bQuery.add(query, Occur.SHOULD);
				
				boolean agentLogged = SecurityUtil.checkLoggedRole(Agent.class);
				if (agentLogged) {
					float similarity = 0.8f;
					int maxEdits = (int) Math.floor((1 - similarity)*term.field().length());
					FuzzyQuery fuzzyQuery = new FuzzyQuery(term, maxEdits);
					bQuery.add(fuzzyQuery, Occur.SHOULD);
					
					PhraseQuery phraseQuery = new PhraseQuery();
					phraseQuery.add(term);
					bQuery.add(phraseQuery, Occur.SHOULD);
					
					PrefixQuery prefixQuery = new PrefixQuery(term);
					bQuery.add(prefixQuery, Occur.SHOULD);
				}
			}
			
			return ResultRetriever.getResults(bQuery, this.indexDirPath);
		} catch (ParseException e) {
			throw new IllegalArgumentException("Prosledjeni term nije u redu");
		}
	}

	private Query createQuery(Term term) throws ParseException {
		QueryParser qp = new QueryParser(v, term.field(), analyzer);
		Query query = qp.parse(term.text());
		return query;
	}
	
}
